#pragma once
#include <iostream>
#include "Socket.hpp"
#include "InetAddr.hpp"
#include <memory>
#include "HandlerConnection.hpp"
#include "common.hpp"
using namespace sock_ns;

class Listener
{
public:
    Listener(int16_t port,HandlerConnection& hc)
        :_port(port)
        ,_listener(std::make_unique<TcpSocket>())
        ,_hc(hc)
    {
        InetAddr addr("0",port);
        _listener->BuildListenSocket(addr);
    }


    ~Listener()
    {
        _listener->Close();
    }

    void Accepter(Connection* conn)
    {

        //ET模式下，接受新的套接字和读写一直做到报错
        while(1)
        {
            errno = 0;
            InetAddr clientaddr;
            int newfd = _listener->Accepter(&clientaddr);

            if(newfd>0)//如果fd>0的话，添加新的conn到reactor中
            {
                //设置非阻塞！！
                SetNonBlock(newfd);
                //通过自带的conn找到reactor
                conn->_R->AddConnection(
                    newfd,
                    EPOLLIN|EPOLLET,
                    std::bind(&HandlerConnection::HandlerRecv,&_hc,std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerSend,&_hc,std::placeholders::_1),
                    std::bind(&HandlerConnection::HandlerExcpet,&_hc,std::placeholders::_1)
                    );
            }
            else
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    Log(DEBUG,"accept all link!");
                    break;
                }
                else if(errno==EINTR)//被信号中断，需要继续读取
                {
                    Log(DEBUG,"accept interupt by sign! continue");
                    continue;
                }
                else//异常了 
                {
                    Log(WARNING,"accept error!");
                    break;
                }
            }
        }
    }

    void HanlderExcpet(Connection *conn)
    {
        errno = 0;
        Log(DEBUG, "client quit : %d\n",conn->Sockfd());
        conn->_R->RemoveConnection(conn->Sockfd());
    }


    int Sockfd()
    {
        return _listener->SockFd();
    }

private:
    int16_t _port;
    std::unique_ptr<Socket> _listener;
    HandlerConnection _hc;
};